﻿using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Canteen.Core.Common
{
    public class Wechat : IWechat
    {
        private readonly HttpClient _client;
        public Wechat(
            HttpClient httpClient,
            IOptions<WechatGzhOptions> options)
        {
            _client = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
            Options = options?.Value ?? throw new ArgumentNullException(nameof(options));
            _client.BaseAddress = new Uri("https://api.weixin.qq.com");
        }

        private async Task<string> Client(string Url)
        {
            using HttpResponseMessage response = await _client.GetAsync(Url);
            //确保Http响应成功  响应状态码为200
            if (response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
            {
                string result = Encoding.UTF8.GetString(await response.Content.ReadAsByteArrayAsync());//异步读取json
                if (string.IsNullOrWhiteSpace(result)) throw new Exception("响应为空");
                return result;
            }
            else throw new Exception("响应失败");
        }

        public WechatGzhOptions Options { get; private set; }

        public async Task<WechatResponseAccessToken> RequestWechatGzhAccessTokenAsync()
        {
            string url = $"/cgi-bin/token?grant_type=client_credential&appid={Options.AppID}&secret={Options.AppSecret}";
            string result = await Client(url);
            if (result.ToLower().Contains("access_token"))
            {
                return JsonConvert.DeserializeObject<WechatResponseAccessToken>(result);
            }
            else
            {
                var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
                throw new Exception($"errcode={err.errcode},errmsg={err.errmsg}");
            }
        }
        public async Task<WechatGzhResponseAccessToken> RequestWechatGzhAuthAccessTokenAsync(string Code)
        {
            string url = $"/sns/oauth2/access_token?appid={Options.AppID}&secret={Options.AppSecret}&code={Code}&grant_type=authorization_code";
            string result = await Client(url);
            if (result.ToLower().Contains("access_token"))
            {
                return JsonConvert.DeserializeObject<WechatGzhResponseAccessToken>(result);
            }
            else
            {
                var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
                throw new Exception($"errcode={err.errcode},errmsg={err.errmsg}");
            }
        }
        public async Task<WechatGzhResponseAccessToken> RefreshWechatGzhAccessTokenAsync(string RefreshToken)
        {
            string url = $"/sns/oauth2/refresh_token?appid={Options.AppID}&grant_type=refresh_token&refresh_token={RefreshToken}";
            string result = await Client(url);
            if (result.ToLower().Contains("access_token"))
            {
                return JsonConvert.DeserializeObject<WechatGzhResponseAccessToken>(result);
            }
            else
            {
                var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
                if (err.errcode == 42002) throw new Exception("刷新凭证(refresh_token)已过期");
                throw new Exception($"errcode={err.errcode},errmsg={err.errmsg}");
            }
        }
        public async Task<WechatGzhResponseUserInfo> RequestWechatGzhUserInfoAsync(WechatGzhResponseAccessToken token)
        {
            string url = $"/sns/userinfo?access_token={token.access_token}&openid={token.openid}&lang=zh_CN";
            string result = await Client(url);
            if (result.ToLower().Contains("openid"))
            {
                return JsonConvert.DeserializeObject<WechatGzhResponseUserInfo>(result);
            }
            else
            {
                var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
                switch (err.errcode)
                {
                    case 42001:
                        var refreshToken = await RefreshWechatGzhAccessTokenAsync(token.refresh_token);//通过刷新凭证(refresh_token)换取新的token
                        return await RequestWechatGzhUserInfoAsync(refreshToken);
                    case 42007: throw new Exception("用户修改了密码，需要重新授权");
                    default: throw new Exception($"errcode={err.errcode},errmsg={err.errmsg}");
                }
            }
        }
        public async Task<bool> RequestWechatGzhAccessTokenExistsAsync(string AccessToken, string Openid)
        {
            string url = $"/sns/auth?access_token={AccessToken}&openid={Openid}";
            string result = await Client(url);
            var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
            //if (err.errcode != 0) { }  TODO:记录日志
            return err.errcode == 0;
        }
        public async Task<WechatGzhResponseJSAPITicket> RequestWechatGzhJSAPITicket(string AccessToken)
        {
            string url = $"/cgi-bin/ticket/getticket?access_token={AccessToken}&type=jsapi";
            string result = await Client(url);
            if (result.ToLower().Contains("ticket"))
            {
                var res = JsonConvert.DeserializeObject<WechatGzhResponseJSAPITicket>(result);
                if (res.errcode == 0) return res;
                else throw new Exception($"errcode={res.errcode},errmsg={res.errmsg}");
            }
            else
            {
                var err = JsonConvert.DeserializeObject<WechatGzhResponseError>(result);
                throw new Exception($"errcode={err.errcode},errmsg={err.errmsg}");
            }
        }
    }
}
